home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / emacssrc.zip / EMACSSRC.TAR / emacs-19.17 / src / hftctl.c < prev    next >
C/C++ Source or Header  |  1993-07-23  |  12KB  |  341 lines

  1. /* IBM has disclaimed copyright on this module.  */
  2.  
  3. /***************************************************************/
  4. /*                                                             */
  5. /* Function: hftctl                                            */
  6. /*                                                             */
  7. /* Syntax:                                                     */
  8. /*    #include <sys/ioctl.h>                                   */
  9. /*    #include <sys/hft.h>                                     */
  10. /*                                                             */
  11. /*    int hftctl(fildes, request, arg )                        */
  12. /*    int fildes, request;                                     */
  13. /*    char *arg;                                               */
  14. /*                                                             */
  15. /* Description:                                                */
  16. /*                                                             */
  17. /*    Does the following:                                      */
  18. /*      1. determines if fildes is pty                         */
  19. /*         does normal ioctl it is not                         */
  20. /*      2. places fildes into raw mode                         */
  21. /*      3. converts ioctl arguments to datastream              */
  22. /*      4. waits for 2 secs for acknowledgement before         */
  23. /*         timing out.                                         */
  24. /*      5. places response in callers buffer ( just like       */
  25. /*         ioctl.                                              */
  26. /*      6. returns fildes to its original mode                 */
  27. /*                                                             */
  28. /*    User of this program should review steps 1,4, and 3.     */
  29. /*    hftctl makes no check on the request type. It must be    */
  30. /*    a HFT ioctl that is supported remotely.                  */
  31. /*    This program will use the SIGALRM and alarm(2).  Any     */
  32. /*    Previous alarms are lost.                                */
  33. /*                                                             */
  34. /*    Users of this program are free to modify it any way      */
  35. /*    they want.                                               */
  36. /*                                                             */
  37. /* Return Value:                                               */
  38. /*                                                             */
  39. /*    If ioctl fails, a value of -1 is returned and errno      */
  40. /*    is set to indicate the error.                            */
  41. /*                                                             */
  42. /***************************************************************/
  43.  
  44.  
  45. #include <stdio.h>
  46. #include <fcntl.h>
  47. #include <errno.h>
  48. #include <setjmp.h>
  49. #include <sys/ioctl.h>
  50. #include <sys/signal.h>
  51. #include <sys/devinfo.h>
  52. #include <termios.h>
  53. #include <termio.h>
  54. #include <sys/hft.h>
  55. #include <sys/uio.h>
  56. #include <sys/tty.h>
  57. /* #include <sys/pty.h> */
  58. #define REMOTE 0x01
  59.  
  60. #undef ioctl
  61. static char     SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90";
  62.  
  63. /*************** LOCAL DEFINES **********************************/
  64.  
  65. typedef int    (*FUNC)();     /* pointer to a function        */
  66.  
  67. #define QDEV   ((HFQPDEVCH<<8)|HFQPDEVCL)
  68. #define QLOC   ((HFQLOCCH<<8)|HFQLOCCL)
  69. #define QPS    ((HFQPRESCH<<8)|HFQPRESCL)
  70.  
  71. #ifndef TCGETS 
  72. #define TCGETS TCGETA
  73. #endif
  74. #ifndef TCSETS
  75. #define TCSETS TCSETA
  76. #endif
  77.  
  78. /*************** EXTERNAL / GLOBAL DATA AREA ********************/
  79.  
  80. static int              hfqry();
  81. static int              hfskbd();
  82.        char            *xmalloc();
  83.  
  84. extern int              errno;
  85. static jmp_buf          hftenv;
  86. static int              is_ack_vtd;
  87. static FUNC             sav_alrm;
  88. static struct hfctlreq  req =
  89.             { 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL};
  90. static struct hfctlack  ACK =
  91.             { 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL};
  92.  
  93.        /* FUNC             signal(); */
  94.  
  95. /*************** LOCAL MACROS ***********************************/
  96.  
  97. #define HFTYPE(p)   ((p->hf_typehi<<8)|(p->hf_typelo))
  98.  
  99. #define BYTE4(p)    ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3])
  100.  
  101.                     /* read a buffer        */
  102. #define RD_BUF(f,p,l) \
  103.         while ((l)) \
  104.           if ((j = read((f),(p),(l))) < 0) \
  105.              if (errno != EINTR) return (-1); \
  106.              else continue; \
  107.           else { (l) -= j; (p) += j; }
  108.  
  109. /*************** function prototypes ***************************/
  110. #ifdef __STDC__
  111. static GT_ACK (int fd, int req, char *buf);
  112. static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen);
  113. static void hft_alrm(int sig);
  114. #else
  115. static GT_ACK ();
  116. static WR_REQ ();
  117. static void hft_alrm ();
  118. #endif
  119.  
  120. /*************** HFTCTL FUNCTION *******************************/
  121.  
  122. hftctl (fd, request, arg)
  123.      int     fd;
  124.      int     request;
  125.      union {
  126.        struct hfintro *intro;
  127.        struct hfquery *query;
  128.        char           *c;
  129.      } arg;
  130. {
  131.  
  132.   int             i;
  133.   int             fd_flag;    /* fcntl flags          */
  134.   register union {
  135.     struct hfintro         *cmd; /* p.cmd - intro des.   */
  136.     struct hfqphdevc       *ph;    /* p.ph  - physical dev.*/
  137.     char            *c;        /* p.c   - char ptr     */
  138.   }               p;        /* general pointer      */
  139.   int             pty_new;    /* pty modes            */
  140.   int             pty_old;
  141.   int             retcode;
  142.   struct termios   term_new;    /* terminal attributes  */
  143.   struct termios   term_old;
  144.   struct devinfo    devInfo; /* defined in sys/devinfo.h */
  145.  
  146.  
  147.   if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1);
  148.  
  149.   if (devInfo.devtype != DD_PSEU) /* is it a pty? */
  150.     return (ioctl(fd, request, arg)); /* no, do IOCTL */
  151.  
  152.   /******* START PTY **************/
  153.   /**  Pty found, possible HFT    */
  154.   /** set new file des as raw     */
  155.   /** as you can.                 */
  156.   /********************************/
  157.  
  158.   /* Get current state of file    */
  159.   /* descriptor & save            */
  160.   if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1);
  161.   if (ioctl (fd, TCGETS, &term_old) == -1) return (-1);
  162.   /* set terminal attr to raw     */
  163.   /* and to delay on read         */
  164.   pty_new = pty_old | REMOTE;
  165.   memcpy (&term_new, &term_old, sizeof (term_new));
  166.   term_new.c_iflag = 0;
  167.   term_new.c_oflag = 0;
  168.   term_new.c_lflag = 0;
  169.   /* term_new.c_line  = 0; */
  170.   for (i = 1; i <= 5; i++)
  171.     term_new.c_cc[i] = 0;
  172.   term_new.c_cc[0] = -1;
  173.   ioctl (fd, TCSETS, &term_new);
  174.   if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1)
  175.     return(-1);
  176.   /* call spacific function       */
  177.   if (request == HFSKBD)
  178.     retcode = hfskbd (fd, request, arg.c);
  179.   else                /* assume HFQUERY */
  180.     retcode = hfqry (fd, request, arg.c);
  181.  
  182.   fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original   */
  183.   ioctl (fd, TCSETS, &term_old);
  184.  
  185.  
  186.   return (retcode);             /* return error                 */
  187. }
  188.  
  189. /*************** HFSKBD  FUNCTION ******************************/
  190. static int
  191. hfskbd (fd, request, arg)
  192.         int     fd;
  193.         int     request;
  194.         struct hfbuf *arg;
  195. {
  196.   WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0);
  197.   return (GT_ACK(fd, request, arg->hf_bufp));
  198. }
  199.  
  200. /*************** HFQUERY FUNCTION ******************************/
  201. static int
  202. hfqry (fd, request, arg)
  203.         int     fd;
  204.         int     request;
  205.         struct hfquery *arg;
  206. {
  207.   WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen);
  208.   return (GT_ACK(fd, request, arg->hf_resp));
  209. }
  210.  
  211.  
  212. /*************** GT_ACK FUNCTION ******************************/
  213. static int
  214. GT_ACK (fd, req, buf)
  215.         int     fd;
  216.         int     req;
  217.         char   *buf;
  218. {
  219.   struct hfctlack ack;
  220.   int             i = sizeof (ack);
  221.   int             j = 0;
  222.   union {
  223.     char            *c;
  224.     struct hfctlack *ack;
  225.   }               p;
  226.  
  227.   is_ack_vtd = 0;        /* flag no ACT VTD yet         */
  228.  
  229.   if (setjmp (hftenv))        /* set environment in case     */
  230.     {                /* of time out                 */
  231.       errno = ENODEV;        /* if time out, set errno      */
  232.       return (-1);        /* flag error                  */
  233.     }
  234.  
  235.   alarm(3);            /* time out in 3 secs          */
  236.   sav_alrm = signal (SIGALRM, hft_alrm); /* prepare to catch time out   */
  237.  
  238.   p.ack = &ack;
  239.   while (! is_ack_vtd)        /* do until valid ACK VTD      */
  240.     {
  241.       RD_BUF(fd, p.c, i);    /* read until a ACK VTD is fill*/
  242.  
  243.       if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro &  */
  244.       && (ack.hf_request == req)) /* is it the response we want ?*/
  245.     {            /* yes, ACK VTD found          */
  246.       is_ack_vtd = 1;    /* quickly, flag it            */
  247.       break;        /* get the %$%#@ out of here   */
  248.     }
  249.  
  250.       p.ack = &ack;        /* no, then skip 1st           */
  251.       ++p.c;            /* char and start over         */
  252.       i = sizeof (ack) - 1;    /* one less ESC to cry over    */
  253.  
  254.       while ((*p.c != 0x1b) && i) /* scan for next ESC           */
  255.     { ++p.c; --i; }        /* if any                      */
  256.  
  257.       (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */
  258.       p.ack = &ack;        /* ESC to front of ack struct  */
  259.       p.c += i;            /* skip over whats been read   */
  260.       i = sizeof (ack) - i;    /* set whats left to be read   */
  261.     }                /***** TRY AGAIN               */
  262.  
  263.   alarm(0);            /* ACK VTD received, reset alrm*/
  264.   signal (SIGALRM, sav_alrm);    /* reset signal                */
  265.  
  266.   if (i = ack.hf_arg_len)    /* any data following ?        */
  267.     {                /* yes,                        */
  268.       RD_BUF(fd,buf,i);        /* read until it is received   */
  269.     }
  270.  
  271.   if (errno = ack.hf_retcode)    /* set errno based on returned */
  272.     return (-1);        /* code, if 0, then no error   */
  273.   else
  274.     return (0);            /* if set, then error returned */
  275. }
  276.  
  277. /*************** HFT_ALRM FUNCTION ******************************/
  278. static void
  279. hft_alrm (sig)                  /* Function hft_alrm - handle */
  280.      int sig;            /* alarm signal              */
  281. {
  282.   signal (SIGALRM, sav_alrm);    /* reset to previous          */
  283.  
  284.   if (is_ack_vtd)        /* has ack vtd arrived ?      */
  285.     return;            /* yes, then continue         */
  286.   else                /* no, then return with error */
  287.     longjmp (hftenv, -1);
  288.  
  289. }
  290.  
  291. /*********************************************************************/
  292. /***                                                               ***/
  293. /***  NOTE: Both the HFCTLREQ and the arg structure should be      ***/
  294. /***        sent in one io write operation.  If terminal           ***/
  295. /***        emulators are in NODELAY mode then multiple writes     ***/
  296. /***        may cause bogus information to be read by the emulator ***/
  297. /***        depending on the timing.                               ***/
  298. /***                                                               ***/
  299. /*********************************************************************/
  300.  
  301. static int
  302. WR_REQ (fd, request, cmdlen, cmd, resplen)
  303.     int             fd;
  304.     int             request;
  305.     int             cmdlen;
  306.     char           *cmd;
  307.     int             resplen;
  308. {
  309.   struct {
  310.     char            *c;
  311.     struct hfctlreq *req;
  312.   }              p;
  313.   int            size;
  314.  
  315.   req.hf_request = request;
  316.   req.hf_arg_len = cmdlen;
  317.   req.hf_rsp_len = resplen;
  318.  
  319.   if (cmdlen)            /* if arg structure to pass    */
  320.     {
  321.       size = sizeof (struct hfctlreq) + cmdlen;
  322.       if ((p.c = xmalloc(size)) == NULL) /* malloc one area            */
  323.     return (-1);
  324.  
  325.       memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct         */
  326.       memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct     */
  327.     }
  328.   else
  329.     {
  330.       p.req = &req;        /* otherwise use only CTL REQ  */
  331.       size = sizeof (req);
  332.     }
  333.  
  334.   /* write request to terminal   */
  335.   if (write(fd,p.c,size) == -1) return (-1);
  336.   if (p.req != &req)        /* free if allocated           */
  337.     xfree (p.c);
  338.   return (0);
  339.  
  340. }
  341.